home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 1.0 beta / flock-1.0RC3.en-US.win32.exe / flock / components / nsBookmarkTransactionManager.js < prev    next >
Text File  |  2007-10-18  |  22KB  |  535 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is bookmark transaction code.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  *   Joey Minta <jminta@gmail.com>
  18.  *
  19.  * Portions created by the Initial Developer are Copyright (C) 2006
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. function bookmarkTransactionManager() {
  39.     this.wrappedJSObject = this;
  40.     this.mTransactionManager = Components.classes["@mozilla.org/transactionmanager;1"]
  41.                                          .createInstance(Components.interfaces.nsITransactionManager);
  42.  
  43.     this.mBatchCount = 0;
  44.  
  45.     this.classInfo = {
  46.         getInterfaces: function (count) {
  47.             var ifaces = [
  48.                 Components.interfaces.nsISupports,
  49.                 Components.interfaces.nsIClassInfo
  50.             ];
  51.             count.value = ifaces.length;
  52.             return ifaces;
  53.         },
  54.  
  55.         getHelperForLanguage: function (language) {
  56.             return null;
  57.         },
  58.  
  59.         contractID: "@mozilla.org/bookmarks/transactionManager;1",
  60.         classDescription: "Booksmarks Transaction Manager",
  61.         classID: Components.ID("{62d2f7fb-acd2-4876-aa2d-b607de9329ff}"),
  62.         implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
  63.         flags: 0
  64.     };
  65.  
  66.     // Define our transactions
  67.     function bkmkTxn() {
  68.         this.item    = null;
  69.         this.parent  = null;
  70.         this.index   = null;
  71.         this.removedProp = null;
  72.     };
  73.  
  74.     bkmkTxn.prototype = {
  75.         BMDS: null,
  76.  
  77.         QueryInterface: function bkmkTxnQI(iid) {
  78.             if (!iid.equals(Components.interfaces.nsITransaction) &&
  79.                 !iid.equals(Components.interfaces.nsISupports))
  80.             throw Components.results.NS_ERROR_NO_INTERFACE;
  81.  
  82.             return this;
  83.         },
  84.  
  85.         merge               : function (aTxn)   {return false},
  86.         getHelperForLanguage: function (aCount) {return null},
  87.         getInterfaces       : function (aCount) {return null},
  88.         canCreateWrapper    : function (aIID)   {return "AllAccess"},
  89.  
  90.         RDFCU: Components.classes["@mozilla.org/rdf/container-utils;1"]
  91.                          .getService(Components.interfaces.nsIRDFContainerUtils),
  92.  
  93.         getParents: function getParents(aResource) {
  94.             var parents = [];
  95.             var arcs = this.BMDS.ArcLabelsIn(aResource);
  96.             while (arcs && arcs.hasMoreElements()) {
  97.                 var testresource = arcs.getNext();
  98.                 if (testresource && testresource.QueryInterface) {
  99.                     testresource.QueryInterface(Components.interfaces.nsIRDFResource);
  100.                     if (this.RDFCU.IsOrdinalProperty(testresource)) {
  101.                         var source = this.BMDS.GetSource(testresource, aResource, true)
  102.                                          .QueryInterface(Components.interfaces.nsIRDFResource);
  103.                         if (parents.indexOf(source) == -1) {
  104.                           //dump("CDC: found parent: "+source.Value+"\n");
  105.                           parents.push(source);
  106.                         }
  107.                     }
  108.                 }
  109.             }
  110.             //dump("CDC: found "+parents.length+" parents\n");
  111.             return parents;
  112.         },
  113.  
  114.         mAssertProperties: function bkmkTxnAssertProps(aProps) {
  115.             if (!aProps) {
  116.                 return;
  117.             }
  118.  
  119.             //for each (var prop in aProps) { // Mozilla bug. Bruno
  120.                 for (var i = 0; i < this.Properties.length; i++) {
  121.                     var oldValue = this.BMDS.GetTarget(this.item, this.Properties[i], true);
  122.                     // must check, if paste call after copy the oldvalue didn't remove.
  123.                     if (!oldValue) {
  124.                         var newValue = aProps[i];
  125.                         if (newValue) {
  126.                             this.BMDS.Assert(this.item, 
  127.                                              this.Properties[i], 
  128.                                              newValue, true);
  129.                         }
  130.                     } else {
  131.                         this.removedProp[i] = oldValue;
  132.                     }
  133.                 }
  134.             //}
  135.         },
  136.  
  137.         mUnassertProperties: function bkmkTxnUnassertProps(aProps) {
  138.             if (!aProps) {
  139.                 return;
  140.             }
  141.             //for each (var prop in aProps) {// Mozilla bug. Bruno
  142.                 for (var i = 0; i < this.Properties.length; i++) {
  143.                     var oldValue = aProps[i];
  144.                     if (oldValue) {
  145.                         this.BMDS.Unassert(this.item, this.Properties[i], oldValue);
  146.                     }
  147.                 }
  148.             //}
  149.         }
  150.     };
  151.  
  152.     bkmkTxn.prototype.RDFC = 
  153.             Components.classes["@mozilla.org/rdf/container;1"]
  154.                       .createInstance(Components.interfaces.nsIRDFContainer);
  155.     var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  156.                                .getService(Components.interfaces.nsIRDFService);
  157.     bkmkTxn.prototype.BMDS = rdfService.GetDataSource("rdf:flock-favorites");
  158.  
  159.     bkmkTxn.prototype.Properties = 
  160.             [rdfService.GetResource("http://home.netscape.com/NC-rdf#Name"),
  161.              rdfService.GetResource("http://home.netscape.com/NC-rdf#URL"),
  162.              rdfService.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL"),
  163.              rdfService.GetResource("http://home.netscape.com/NC-rdf#Description"),
  164.              rdfService.GetResource("http://home.netscape.com/NC-rdf#WebPanel"),
  165.              rdfService.GetResource("http://home.netscape.com/NC-rdf#FeedURL"),
  166.              rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumGenURI"),
  167.              rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumExpiration"),
  168.              rdfService.GetResource("http://home.netscape.com/NC-rdf#GeneratedTitle"),
  169.              rdfService.GetResource("http://home.netscape.com/NC-rdf#BookmarkAddDate"),
  170.              rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastModifiedDate"),
  171.              rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastVisitDate"),
  172.              rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastCharset"),
  173.              rdfService.GetResource("http://flock.com/rdf#flockType"),
  174.              rdfService.GetResource("http://flock.com/rdf#isTransient"),
  175.              rdfService.GetResource("http://flock.com/rdf#isIndexable"),
  176.              rdfService.GetResource("http://flock.com/rdf#unseenItems"),
  177.              rdfService.GetResource("http://flock.com/rdf#count"),
  178.              rdfService.GetResource("http://flock.com/rdf#maxItems"),
  179.              rdfService.GetResource("http://flock.com/rdf#capItems"),
  180.              rdfService.GetResource("http://flock.com/rdf#hasUnseenItems"),
  181.              rdfService.GetResource("http://flock.com/rdf#isPollable"),
  182.              rdfService.GetResource("http://flock.com/rdf#refreshing"),
  183.              rdfService.GetResource("http://flock.com/rdf#shared"),
  184.              rdfService.GetResource("http://flock.com/rdf#favicon"),
  185.              rdfService.GetResource("http://flock.com/rdf#tags"),
  186.              rdfService.GetResource("http://flock.com/rdf#lastItemDate"),
  187.              rdfService.GetResource("http://flock.com/rdf#lastRefresh"),
  188.              rdfService.GetResource("http://flock.com/rdf#lastQuery"),
  189.              rdfService.GetResource("http://flock.com/rdf#refreshInterval"),
  190.              rdfService.GetResource("http://flock.com/rdf#datevalue"),
  191.              rdfService.GetResource("http://flock.com/rdf#CoopType"),
  192.              rdfService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")];
  193.  
  194.     function bkmkInsertTxn(aAction) {
  195.         this.type = "insert";
  196.         // move container declaration to here so it can be recognized if
  197.         // undoTransaction is call after the BM manager is close and reopen.
  198.         this.container = Components.classes["@mozilla.org/rdf/container;1"]
  199.                                    .createInstance(Components.interfaces.nsIRDFContainer);
  200.     }
  201.  
  202.     bkmkInsertTxn.prototype = {
  203.          __proto__: bkmkTxn.prototype,
  204.  
  205.          isTransient: false,
  206.  
  207.          doTransaction: function bkmkInsertDoTxn() {
  208.              this.RDFC.Init(this.BMDS, this.parent);
  209.              // if the index is -1, we use appendElement, and then update the
  210.              // index so that undoTransaction can still function
  211.              if (this.index == -1) {
  212.                  this.RDFC.AppendElement(this.item);
  213.                  this.index = this.RDFC.GetCount();
  214.              } else {
  215. /*XXX- broken insert code, see bug 264571
  216.                  try {
  217.                      this.RDFC.InsertElementAt(this.item, this.index, true);
  218.                  } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
  219.                      // if this failed, then we assume that we really want to append,
  220.                      // because things are out of whack until we renumber.
  221.                      this.RDFC.AppendElement(this.item);
  222.                      // and then fix up the index so undo works
  223.                      this.index = this.RDFC.GetCount();
  224.                  }
  225. */
  226.                  this.RDFC.InsertElementAt(this.item, this.index, true);
  227.              }
  228.  
  229.              // insert back all the properties
  230.              this.mAssertProperties(this.removedProp);
  231.          },
  232.  
  233.          undoTransaction: function bkmkInsertUndoTxn() {
  234.              // XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
  235.              this.container.Init(this.BMDS, this.parent);
  236.  
  237.              // remove all properties befor we remove the element so
  238.              // nsLocalSearchService doesn't return deleted element in Search
  239.              this.mUnassertProperties(this.removedProp);
  240.  
  241.              this.container.RemoveElementAt(this.index, true);
  242.          },
  243.  
  244.          redoTransaction: function bkmkInsertRedoTxn() {
  245.              this.doTransaction();
  246.          }
  247.     };
  248.  
  249.     function bkmkRemoveTxn() {
  250.         this.type    = "remove";
  251.     }
  252.  
  253.     bkmkRemoveTxn.prototype = {
  254.         __proto__: bkmkTxn.prototype,
  255.  
  256.         isTransient: false,
  257.  
  258.         doTransaction: function bkmkRemoveDoTxn() {
  259.             this.RDFC.Init(this.BMDS, this.parent);
  260.  
  261.             // remove all properties befor we remove the element so
  262.             // nsLocalSearchService doesn't return deleted element in Search
  263.             this.mUnassertProperties(this.removedProp);
  264.  
  265.             this.RDFC.RemoveElementAt(this.index, false);
  266.         },
  267.  
  268.         undoTransaction: function bkmkRemoveUndoTxn() {
  269.             this.RDFC.Init(this.BMDS, this.parent);
  270.             this.RDFC.InsertElementAt(this.item, this.index, false);
  271.  
  272.             // insert back all the properties
  273.             this.mAssertProperties(this.removedProp);
  274.         },
  275.  
  276.         redoTransaction: function () {
  277.             this.doTransaction();
  278.         }
  279.     }
  280.  
  281.     function bkmkRemoveAllTxn() {
  282.         this.type    = "removeAll";
  283.     }
  284.  
  285.     bkmkRemoveAllTxn.prototype = {
  286.         __proto__: bkmkTxn.prototype,
  287.  
  288.         isTransient: false,
  289.  
  290.         childContainer:
  291.             Components.classes["@mozilla.org/rdf/container;1"]
  292.                       .createInstance(Components.interfaces.nsIRDFContainer),
  293.  
  294.         doTransaction: function bkmkRemoveDoTxn() {
  295.             this.item.QueryInterface(Components.interfaces.nsIRDFResource);
  296.             //dump("CDC: bkmkRemoveAllDoTxn('"+this.item.Value+"')\n"); 
  297.  
  298.             checkTopSitesRequirement = function checkTopSitesRequirement(aParents) {
  299.               for(var i=0;i<aParents.length;i++) {
  300.                 var parent = aParents[i];
  301.  
  302.                 if(parent.Value == "urn:flock:topsites") {
  303.                   return true;
  304.                 }
  305.               }
  306.               
  307.               return false;
  308.             };
  309.  
  310.             // When 'deleting' a bookmark item, we only want to REALLY delete
  311.             // it if it has EXACTLY one parent
  312.             if ( (this.getParents(this.item).length == 1) 
  313.                  || (this.getParents(this.item).length == 2 && checkTopSitesRequirement(this.getParents(this.item)))
  314.                ) {
  315.                 // First, recursively delete any children of this one...
  316.                 if (this.RDFCU.IsContainer(this.BMDS, this.item)) {
  317.                     this.childContainer.Init(this.BMDS, this.item);
  318.                     var children = this.childContainer.GetElements();
  319.                     this.mSubTransactions = [];
  320.                     while (children && children.hasMoreElements()) {
  321.                         var child = children.getNext();
  322.                         var txn = new bkmkRemoveAllTxn();
  323.                         txn.item = child;
  324.                         txn.parent = this.item;
  325.                         txn.index = this.childContainer.IndexOf(child);
  326.                         txn.action = this.action;
  327.                         txn.removedProp = [];
  328.                         for (var i = 0; i < this.Properties.length; i++) {
  329.                             txn.removedProp[i] = this.BMDS.GetTarget(child, this.Properties[i], true);
  330.                         }
  331.                         txn.wrappedJSObject = txn;
  332.                         this.mSubTransactions.push(txn);
  333.                     }
  334.                     for (var i = 0; i < this.mSubTransactions.length; i++) {
  335.                         this.mSubTransactions[i].doTransaction();
  336.                     }
  337.                 }
  338.  
  339.                 // Remove all properties before we remove the element so
  340.                 // nsLocalSearchService doesn't return deleted element in Search
  341.                 this.mUnassertProperties(this.removedProp);
  342.             }
  343.  
  344.             // Remove the item from its parent (this always gets done,
  345.             // regardless of how many other parents there might be)
  346.              //dump("CDC: bkmkRemoveAllDoTxn "+this.index+"\n"); 
  347.             try {
  348.               this.RDFC.Init(this.BMDS, this.parent);
  349.               //If index == -1 then we  don't have an index to remove 
  350.               // this can happen when bookmark is created and then removed, it might not have an index
  351.               if(this.index > -1)
  352.                 this.RDFC.RemoveElementAt(this.index, false);
  353.             }catch(e)
  354.             {
  355.             }
  356.             
  357.         },
  358.  
  359.         undoTransaction: function bkmkRemoveUndoTxn() {
  360.             // Reinstate the arc to the main parent
  361.             this.RDFC.Init(this.BMDS, this.parent);
  362.             this.RDFC.InsertElementAt(this.item, this.index, false);
  363.  
  364.             if (this.getParents(this.item).length == 1) {
  365.                 // insert back all the properties
  366.                 this.mAssertProperties(this.removedProp);
  367.  
  368.                 // Undo all the sub-transactions (contained bookmarks)
  369.                 if (this.mSubTransactions) {
  370.                     for (var i = this.mSubTransactions.length - 1; i >= 0; i--) {
  371.                         this.mSubTransactions[i].undoTransaction();
  372.                         this.mSubTransactions[i] = undefined;
  373.                     }
  374.                     this.mSubTransactions = undefined;
  375.                 }
  376.             }
  377.         },
  378.  
  379.         redoTransaction: function () {
  380.             this.doTransaction();
  381.         }
  382.     }
  383.  
  384.     function bkmkImportTxn(aAction) {
  385.         this.type    = "import";
  386.         this.action  = aAction;
  387.     }
  388.  
  389.     bkmkImportTxn.prototype = {
  390.         __proto__: bkmkTxn.prototype,
  391.  
  392.         isTransient: false,
  393.  
  394.         doTransaction: function bkmkImportDoTxn() {},
  395.  
  396.         undoTransaction: function mkmkImportUndoTxn() {
  397.             this.RDFC.Init(this.BMDS, this.parent);
  398.             this.RDFC.RemoveElementAt(this.index, true);
  399.         },
  400.  
  401.         redoTransaction: function bkmkImportredoTxn() {
  402.             this.RDFC.Init(this.BMDS, this.parent);
  403.             this.RDFC.InsertElementAt(this.item, this.index, true);
  404.         }
  405.     };
  406.  
  407.     this.BookmarkRemoveTransaction = bkmkRemoveTxn;
  408.     this.BookmarkRemoveAllTransaction = bkmkRemoveAllTxn;
  409.     this.BookmarkInsertTransaction = bkmkInsertTxn;
  410.     this.BookmarkImportTransaction = bkmkImportTxn;
  411. }
  412.  
  413. bookmarkTransactionManager.prototype.QueryInterface = function bkTxnMgrQI(aIID) {
  414.     if (aIID.equals(Components.interfaces.nsISupports) ||
  415.         aIID.equals(Components.interfaces.nsIBookmarkTransactionManager)) {
  416.         return this;
  417.     } 
  418.     if (aIID.equals(Components.interfaces.nsIClassInfo)) {
  419.         return this.classInfo;
  420.     }
  421.  
  422.     throw NS_ERROR_NO_INTERFACE;
  423. }
  424.  
  425. bookmarkTransactionManager.prototype.createAndCommitTxn = 
  426. function bkmkTxnMgrCandC(aType, aAction, aItem, aIndex, aParent, aPropCount, aRemovedProps) {
  427.     //dump("CDC: createAndCommitTxn(aType='"+aType+"', aAction='"+aAction+"', aIndex="+aIndex+")\n");
  428.     var txn;
  429.     var nsIBookmarkTransactionManager = Components.interfaces.nsIBookmarkTransactionManager;
  430.     switch (aType) {
  431.         case nsIBookmarkTransactionManager.IMPORT: 
  432.             txn = new this.BookmarkImportTransaction(aAction);
  433.             break;
  434.         case nsIBookmarkTransactionManager.INSERT: 
  435.             txn = new this.BookmarkInsertTransaction(aAction);
  436.             break;
  437.         case nsIBookmarkTransactionManager.REMOVE: 
  438.             if (aAction == "move") {
  439.               txn = new this.BookmarkRemoveTransaction(aAction);
  440.             } else {
  441.               txn = new this.BookmarkRemoveAllTransaction(aAction);
  442.             }
  443.             break;
  444.         default:
  445.             Components.utils.reportError("Unknown bookmark transaction type:"+aType);
  446.             throw NS_ERROR_FAILURE;
  447.     }
  448.     txn.item = aItem;
  449.     txn.parent = aParent;
  450.     txn.index = aIndex;
  451.     txn.removedProp = aRemovedProps;
  452.     txn.action = aAction;
  453.     txn.wrappedJSObject = txn;
  454.     this.mTransactionManager.doTransaction(txn);
  455.     //dump("CDC: end createAndCommitTxn(aType='"+aType+"', aAction='"+aAction+"', aIndex="+aIndex+")\n");
  456. }
  457.  
  458. bookmarkTransactionManager.prototype.startBatch = function bkmkTxnMgrUndo() {
  459.     if (this.mBatchCount == 0) {
  460.         this.mTransactionManager.beginBatch();
  461.     }
  462.     this.mBatchCount++;
  463. }
  464.  
  465. bookmarkTransactionManager.prototype.endBatch = function bkmkTxnMgrUndo() {
  466.     this.mBatchCount--;
  467.     if (this.mBatchCount == 0) {
  468.         this.mTransactionManager.endBatch();
  469.     }
  470. }
  471.  
  472. bookmarkTransactionManager.prototype.undo = function bkmkTxnMgrUndo() {
  473.     this.mTransactionManager.undoTransaction();
  474. }
  475.  
  476. bookmarkTransactionManager.prototype.redo = function bkmkTxnMgrRedo() {
  477.     this.mTransactionManager.redoTransaction();
  478. }
  479.  
  480. bookmarkTransactionManager.prototype.canUndo = function bkmkTxnMgrCanUndo() {
  481.     return this.mTransactionManager.numberOfUndoItems > 0;
  482. }
  483.  
  484. bookmarkTransactionManager.prototype.canRedo = function bkmkTxnMgrCanRedo() {
  485.     return this.mTransactionManager.numberOfRedoItems > 0;
  486. }
  487.  
  488. bookmarkTransactionManager.prototype.__defineGetter__("transactionManager", 
  489. function bkmkTxnMgrGetter() {  return this.mTransactionManager; });
  490.  
  491. /****
  492.  **** module registration
  493.  ****/
  494.  
  495. const kFactory = {
  496.     createInstance: function (outer, iid) {
  497.         if (outer != null)
  498.             throw Components.results.NS_ERROR_NO_AGGREGATION;
  499.         return (new bookmarkTransactionManager()).QueryInterface(iid);
  500.     }
  501. };
  502.  
  503. var bkmkTxnMgrModule = {
  504.     mCID: Components.ID("{8be133d0-681d-4f0b-972b-6a68e41afb62}"),
  505.     mContractID: "@mozilla.org/bookmarks/transactionmanager;1",
  506.     
  507.     registerSelf: function (compMgr, fileSpec, location, type) {
  508.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  509.         compMgr.registerFactoryLocation(this.mCID,
  510.                                         "Bookmark Transaction Manager",
  511.                                         this.mContractID,
  512.                                         fileSpec,
  513.                                         location,
  514.                                         type);
  515.     },
  516.  
  517.     getClassObject: function (compMgr, cid, iid) {
  518.         if (!cid.equals(this.mCID))
  519.             throw Components.results.NS_ERROR_NO_INTERFACE;
  520.  
  521.         if (!iid.equals(Components.interfaces.nsIFactory))
  522.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  523.  
  524.         return kFactory;
  525.     },
  526.  
  527.     canUnload: function(compMgr) {
  528.         return true;
  529.     }
  530. };
  531.  
  532. function NSGetModule(compMgr, fileSpec) {
  533.     return bkmkTxnMgrModule;
  534. }
  535.